/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * ChuckConfigurationForm.java
 *
 * Created on Nov 13, 2009, 4:01:42 PM
 */
package wekinator;

import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import wekinator.OscSynthConfiguration;
import wekinator.ChuckRunner.ChuckRunnerState;
import wekinator.util.OverwritePromptingFileChooser;
import wekinator.util.Util;

/**
 *
 * @author rebecca
 */
public class ChuckConfigurationForm extends javax.swing.JFrame {

    ChuckConfiguration configuration;
    ChuckConfiguration initialConfiguration;
    OscSynthConfigurationFrame2 synthConfigurationFrame = null;
    OscSynthConfiguration synthConfiguration = null;
    String homePath = ".." + File.separator + ".." + File.separator; //TODO: get from settings
    ChangeListener synthChangeListener = new ChangeListener() {

        public void stateChanged(ChangeEvent e) {
            updateOscSynthDescription();
        }
    };

    /** Creates new form ChuckConfigurationForm */
    public ChuckConfigurationForm(ChuckConfiguration c) {
        configuration = c;
        initialConfiguration = new ChuckConfiguration(configuration);
        initComponents();
        synthConfiguration = new OscSynthConfiguration(c.getOscSynthConfiguration()); //Copy from my config
        synthConfiguration.addChangeListener(synthChangeListener);
        String s = Util.getCanonicalPath(new File(""));

        if (WekinatorRunner.isLaunchedOsxApp()) {
            labelWekDirPrompt.setVisible(false);
            labelWekDirHint.setVisible(false);
            labelWekDirCurrent.setVisible(false);
            buttonChangeWekDir.setVisible(false);

        }

        //Hid OSC Features for plork
       // panelOscFeatureExtractor.setVisible(!WekinatorRunner.isPlork());
        repaint();
        updateAllComponents();
    }

    public void setHomePath(String s) {
        homePath = s;
    }

    private File findExportChuckFile() {
        String preferredLoc = configuration.getChuckDir();
        File tmp = new File(preferredLoc);
        if (!tmp.exists()) {
            preferredLoc = homePath;
        }

        JFileChooser fc = new OverwritePromptingFileChooser();

        fc.setSelectedFile(new File(configuration.getChuckDir() + "/main_machine_add_files/config.ck"));
        fc.setDialogType(JFileChooser.SAVE_DIALOG);
        fc.setFileSelectionMode(JFileChooser.FILES_ONLY);

        int returnVal = fc.showSaveDialog(this);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            return fc.getSelectedFile();
        }
        return null;

    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        buttonGroup1 = new javax.swing.ButtonGroup();
        jScrollPane1 = new javax.swing.JScrollPane();
        jPanel3 = new javax.swing.JPanel();
        buttonLoadConfiguration = new javax.swing.JButton();
        buttonSaveConfiguration = new javax.swing.JButton();
        buttonOK = new javax.swing.JButton();
        buttonCancel = new javax.swing.JButton();
        buttonSaveConfiguration1 = new javax.swing.JButton();
        jTabbedPane2 = new javax.swing.JTabbedPane();
        panelFeatures = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        labelCustomFeatureExtractor = new javax.swing.JLabel();
        buttonChooseChuckFeatureExtractor = new javax.swing.JButton();
        checkEnableCustomChuckFeature = new javax.swing.JCheckBox();
        helpFeatures = new javax.swing.JButton();
        panelSynth = new javax.swing.JPanel();
        radioUseChuckSynth = new javax.swing.JRadioButton();
        labelChuckSynthClass = new javax.swing.JLabel();
        labelChuckSynthLocation = new javax.swing.JLabel();
        buttonChooseChuckSynth = new javax.swing.JButton();
        helpSynth = new javax.swing.JButton();
        radioUseOSCSynth = new javax.swing.JRadioButton();
        buttonEditRealInteger = new javax.swing.JButton();
        labelOSCSynthProps = new javax.swing.JLabel();
        panelSetup = new javax.swing.JPanel();
        jLabel3 = new javax.swing.JLabel();
        buttonChangeChuckExecutable = new javax.swing.JButton();
        labelChuckExecutable = new javax.swing.JLabel();
        labelWekDirPrompt = new javax.swing.JLabel();
        buttonChangeWekDir = new javax.swing.JButton();
        labelWekDirCurrent = new javax.swing.JLabel();
        helpCoreChuck = new javax.swing.JButton();
        labelWekDirHint = new javax.swing.JLabel();
        panelPlayalong = new javax.swing.JPanel();
        helpPlayalong = new javax.swing.JButton();
        checkEnablePlayalong = new javax.swing.JCheckBox();
        buttonChoosePlayalongFile = new javax.swing.JButton();
        labelScorePlayer = new javax.swing.JLabel();
        jLabel15 = new javax.swing.JLabel();
        jLabel16 = new javax.swing.JLabel();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);

        jScrollPane1.setPreferredSize(new java.awt.Dimension(620, 390));

        jPanel3.setPreferredSize(new java.awt.Dimension(635, 390));
        jPanel3.setRequestFocusEnabled(false);

        buttonLoadConfiguration.setText("Load configuration...");
        buttonLoadConfiguration.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonLoadConfigurationActionPerformed(evt);
            }
        });

        buttonSaveConfiguration.setText("Save configuration...");
        buttonSaveConfiguration.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonSaveConfigurationActionPerformed(evt);
            }
        });

        buttonOK.setText("OK");
        buttonOK.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonOKActionPerformed(evt);
            }
        });

        buttonCancel.setText("Cancel");
        buttonCancel.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonCancelActionPerformed(evt);
            }
        });

        buttonSaveConfiguration1.setFont(new java.awt.Font("Lucida Grande", 2, 13)); // NOI18N
        buttonSaveConfiguration1.setText("Export as .ck file...");
        buttonSaveConfiguration1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonSaveConfiguration1ActionPerformed(evt);
            }
        });

        jTabbedPane2.setPreferredSize(new java.awt.Dimension(400, 300));

        jLabel1.setText("CustomFeatureExtractor file:");

        labelCustomFeatureExtractor.setText("/user/rebecca/stuff/core_chuck/");

        buttonChooseChuckFeatureExtractor.setText("Choose file");
        buttonChooseChuckFeatureExtractor.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonChooseChuckFeatureExtractorActionPerformed(evt);
            }
        });

        checkEnableCustomChuckFeature.setText("Enable a custom ChucK feature extractor");
        checkEnableCustomChuckFeature.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                checkEnableCustomChuckFeatureActionPerformed(evt);
            }
        });

        helpFeatures.setIcon(new javax.swing.ImageIcon(getClass().getResource("/wekinator/info.png"))); // NOI18N

        org.jdesktop.layout.GroupLayout panelFeaturesLayout = new org.jdesktop.layout.GroupLayout(panelFeatures);
        panelFeatures.setLayout(panelFeaturesLayout);
        panelFeaturesLayout.setHorizontalGroup(
            panelFeaturesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(panelFeaturesLayout.createSequentialGroup()
                .add(panelFeaturesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(org.jdesktop.layout.GroupLayout.TRAILING, panelFeaturesLayout.createSequentialGroup()
                        .addContainerGap()
                        .add(panelFeaturesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                            .add(checkEnableCustomChuckFeature)
                            .add(panelFeaturesLayout.createSequentialGroup()
                                .add(29, 29, 29)
                                .add(jLabel1)))
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(buttonChooseChuckFeatureExtractor)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, 526, Short.MAX_VALUE)
                        .add(helpFeatures))
                    .add(panelFeaturesLayout.createSequentialGroup()
                        .add(52, 52, 52)
                        .add(labelCustomFeatureExtractor, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 921, Short.MAX_VALUE)))
                .addContainerGap())
        );
        panelFeaturesLayout.setVerticalGroup(
            panelFeaturesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(panelFeaturesLayout.createSequentialGroup()
                .add(panelFeaturesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(panelFeaturesLayout.createSequentialGroup()
                        .add(panelFeaturesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                            .add(checkEnableCustomChuckFeature)
                            .add(buttonChooseChuckFeatureExtractor))
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(jLabel1))
                    .add(helpFeatures))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(labelCustomFeatureExtractor, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 16, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(219, Short.MAX_VALUE))
        );

        jTabbedPane2.addTab("Features (input)", panelFeatures);

        buttonGroup1.add(radioUseChuckSynth);
        radioUseChuckSynth.setText("Use a ChucK synth class");
        radioUseChuckSynth.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                radioUseChuckSynthActionPerformed(evt);
            }
        });

        labelChuckSynthClass.setText("/user/rebecca/stuff/core_chuck/");

        labelChuckSynthLocation.setText("Location of SynthClass file:");

        buttonChooseChuckSynth.setText("Choose file...");
        buttonChooseChuckSynth.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonChooseChuckSynthActionPerformed(evt);
            }
        });

        helpSynth.setIcon(new javax.swing.ImageIcon(getClass().getResource("/wekinator/info.png"))); // NOI18N

        buttonGroup1.add(radioUseOSCSynth);
        radioUseOSCSynth.setText("Use a different Max/OSC synth module (launch manually, listen on port 12000)");
        radioUseOSCSynth.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                radioUseOSCSynthActionPerformed(evt);
            }
        });

        buttonEditRealInteger.setText("Configure...");
        buttonEditRealInteger.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonEditRealIntegerActionPerformed(evt);
            }
        });

        labelOSCSynthProps.setText("OSC synth not configured.");
        labelOSCSynthProps.setEnabled(false);

        org.jdesktop.layout.GroupLayout panelSynthLayout = new org.jdesktop.layout.GroupLayout(panelSynth);
        panelSynth.setLayout(panelSynthLayout);
        panelSynthLayout.setHorizontalGroup(
            panelSynthLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(panelSynthLayout.createSequentialGroup()
                .add(panelSynthLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(panelSynthLayout.createSequentialGroup()
                        .addContainerGap()
                        .add(panelSynthLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                            .add(panelSynthLayout.createSequentialGroup()
                                .add(27, 27, 27)
                                .add(labelChuckSynthLocation))
                            .add(panelSynthLayout.createSequentialGroup()
                                .add(radioUseChuckSynth)
                                .add(8, 8, 8)
                                .add(buttonChooseChuckSynth)
                                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                .add(helpSynth))))
                    .add(panelSynthLayout.createSequentialGroup()
                        .add(51, 51, 51)
                        .add(labelChuckSynthClass))
                    .add(panelSynthLayout.createSequentialGroup()
                        .addContainerGap()
                        .add(panelSynthLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                            .add(radioUseOSCSynth)
                            .add(panelSynthLayout.createSequentialGroup()
                                .add(20, 20, 20)
                                .add(buttonEditRealInteger))
                            .add(panelSynthLayout.createSequentialGroup()
                                .add(29, 29, 29)
                                .add(labelOSCSynthProps, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 618, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)))))
                .addContainerGap())
        );
        panelSynthLayout.setVerticalGroup(
            panelSynthLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(panelSynthLayout.createSequentialGroup()
                .add(panelSynthLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(panelSynthLayout.createSequentialGroup()
                        .add(panelSynthLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                            .add(buttonChooseChuckSynth)
                            .add(radioUseChuckSynth))
                        .add(3, 3, 3)
                        .add(labelChuckSynthLocation)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(labelChuckSynthClass))
                    .add(helpSynth))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(radioUseOSCSynth)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(labelOSCSynthProps)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(buttonEditRealInteger)
                .addContainerGap(98, Short.MAX_VALUE))
        );

        jTabbedPane2.addTab("Synthesis (output)", panelSynth);

        jLabel3.setText("Location of chuck executable");

        buttonChangeChuckExecutable.setText("Choose file");
        buttonChangeChuckExecutable.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonChangeChuckExecutableActionPerformed(evt);
            }
        });

        labelChuckExecutable.setText("/Users/rebecca/PLOrk/bin/chuck");

        labelWekDirPrompt.setText("Location of wekinator project directory:");

        buttonChangeWekDir.setText("Choose directory");
        buttonChangeWekDir.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonChangeWekDirActionPerformed(evt);
            }
        });

        labelWekDirCurrent.setText("/Users/rebecca/PLOrk/wekinator/project/");

        helpCoreChuck.setIcon(new javax.swing.ImageIcon(getClass().getResource("/wekinator/info.png"))); // NOI18N

        labelWekDirHint.setFont(new java.awt.Font("Lucida Grande", 2, 13)); // NOI18N
        labelWekDirHint.setText("This should be [directory where you saved wekinator]/wekinator/project");

        org.jdesktop.layout.GroupLayout panelSetupLayout = new org.jdesktop.layout.GroupLayout(panelSetup);
        panelSetup.setLayout(panelSetupLayout);
        panelSetupLayout.setHorizontalGroup(
            panelSetupLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(panelSetupLayout.createSequentialGroup()
                .addContainerGap()
                .add(panelSetupLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(org.jdesktop.layout.GroupLayout.TRAILING, panelSetupLayout.createSequentialGroup()
                        .add(0, 941, Short.MAX_VALUE)
                        .add(helpCoreChuck))
                    .add(panelSetupLayout.createSequentialGroup()
                        .add(panelSetupLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                            .add(panelSetupLayout.createSequentialGroup()
                                .add(jLabel3)
                                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                                .add(buttonChangeChuckExecutable))
                            .add(labelWekDirHint)
                            .add(panelSetupLayout.createSequentialGroup()
                                .add(labelWekDirPrompt)
                                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                                .add(buttonChangeWekDir))
                            .add(panelSetupLayout.createSequentialGroup()
                                .add(24, 24, 24)
                                .add(panelSetupLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                                    .add(labelChuckExecutable)
                                    .add(labelWekDirCurrent))))
                        .addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
        );
        panelSetupLayout.setVerticalGroup(
            panelSetupLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(panelSetupLayout.createSequentialGroup()
                .add(panelSetupLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(panelSetupLayout.createSequentialGroup()
                        .add(panelSetupLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                            .add(jLabel3)
                            .add(buttonChangeChuckExecutable))
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(labelChuckExecutable))
                    .add(helpCoreChuck))
                .add(18, 18, 18)
                .add(panelSetupLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(labelWekDirPrompt)
                    .add(buttonChangeWekDir))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(labelWekDirHint)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(labelWekDirCurrent)
                .addContainerGap(150, Short.MAX_VALUE))
        );

        jTabbedPane2.addTab("System", panelSetup);

        helpPlayalong.setIcon(new javax.swing.ImageIcon(getClass().getResource("/wekinator/info.png"))); // NOI18N

        checkEnablePlayalong.setText("Enable play-along ChucK score");
        checkEnablePlayalong.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                checkEnablePlayalongActionPerformed(evt);
            }
        });

        buttonChoosePlayalongFile.setText("Choose file");
        buttonChoosePlayalongFile.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonChoosePlayalongFileActionPerformed(evt);
            }
        });

        labelScorePlayer.setText("/user/rebecca/stuff/core_chuck/");

        jLabel15.setText("Location of ScorePlayer file:");

        jLabel16.setFont(new java.awt.Font("Lucida Grande", 2, 13)); // NOI18N
        jLabel16.setText("You can use a playalong ChucK score in addition to playing the parameter clipboard.");

        org.jdesktop.layout.GroupLayout panelPlayalongLayout = new org.jdesktop.layout.GroupLayout(panelPlayalong);
        panelPlayalong.setLayout(panelPlayalongLayout);
        panelPlayalongLayout.setHorizontalGroup(
            panelPlayalongLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(panelPlayalongLayout.createSequentialGroup()
                .add(panelPlayalongLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(panelPlayalongLayout.createSequentialGroup()
                        .add(panelPlayalongLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                            .add(panelPlayalongLayout.createSequentialGroup()
                                .add(checkEnablePlayalong)
                                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                                .add(buttonChoosePlayalongFile))
                            .add(panelPlayalongLayout.createSequentialGroup()
                                .addContainerGap()
                                .add(jLabel16)))
                        .add(34, 34, 34)
                        .add(helpPlayalong))
                    .add(panelPlayalongLayout.createSequentialGroup()
                        .add(29, 29, 29)
                        .add(jLabel15))
                    .add(org.jdesktop.layout.GroupLayout.TRAILING, panelPlayalongLayout.createSequentialGroup()
                        .add(35, 35, 35)
                        .add(labelScorePlayer, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
                .addContainerGap())
        );
        panelPlayalongLayout.setVerticalGroup(
            panelPlayalongLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(panelPlayalongLayout.createSequentialGroup()
                .add(panelPlayalongLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(panelPlayalongLayout.createSequentialGroup()
                        .addContainerGap()
                        .add(jLabel16)
                        .add(1, 1, 1)
                        .add(panelPlayalongLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                            .add(checkEnablePlayalong)
                            .add(buttonChoosePlayalongFile)))
                    .add(helpPlayalong))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(jLabel15)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(labelScorePlayer)
                .addContainerGap(196, Short.MAX_VALUE))
        );

        jTabbedPane2.addTab("Playalong", panelPlayalong);

        org.jdesktop.layout.GroupLayout jPanel3Layout = new org.jdesktop.layout.GroupLayout(jPanel3);
        jPanel3.setLayout(jPanel3Layout);
        jPanel3Layout.setHorizontalGroup(
            jPanel3Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(jPanel3Layout.createSequentialGroup()
                .addContainerGap()
                .add(jPanel3Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(jTabbedPane2, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 629, Short.MAX_VALUE)
                    .add(jPanel3Layout.createSequentialGroup()
                        .add(buttonLoadConfiguration)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
                        .add(buttonSaveConfiguration)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
                        .add(buttonSaveConfiguration1))
                    .add(jPanel3Layout.createSequentialGroup()
                        .add(buttonCancel)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(buttonOK)))
                .add(23, 23, 23))
        );
        jPanel3Layout.setVerticalGroup(
            jPanel3Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(jPanel3Layout.createSequentialGroup()
                .addContainerGap()
                .add(jTabbedPane2, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(jPanel3Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(buttonLoadConfiguration)
                    .add(buttonSaveConfiguration)
                    .add(buttonSaveConfiguration1))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(jPanel3Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(buttonCancel)
                    .add(buttonOK))
                .addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        jScrollPane1.setViewportView(jPanel3);

        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .addContainerGap()
                .add(jScrollPane1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 640, Short.MAX_VALUE)
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .add(jScrollPane1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE)
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void setConfigurationFromForm() {
        //Want chuck dir:
        configuration.setChuckExecutable(labelChuckExecutable.getText());
        configuration.setCustomChuckFeatureExtractorEnabled(checkEnableCustomChuckFeature.getModel().isSelected());
        configuration.setCustomChuckFeatureExtractorFilename(labelCustomFeatureExtractor.getText());

        if (WekinatorRunner.isPlork()) {
            configuration.setNumOSCFeaturesExtracted(0);
            configuration.setOscFeatureExtractorEnabled(false);
        } else {
          //  configuration.setOscFeatureExtractorEnabled(checkEnableOSCFeature.getModel().isSelected());
         //   System.out.println("Is osc feat enabled? " + configuration.isOscFeatureExtractorEnabled());
         /*   try {
                int i = Integer.parseInt(textNumOscFeatures.getText());
                configuration.setNumOSCFeaturesExtracted(i);
            } catch (Exception ex) {
                configuration.setNumOSCFeaturesExtracted(0);
                textNumOscFeatures.setText("0");
            } */
        }

        //try {

         //   configuration.setNumCustomChuckFeaturesExtracted(Integer.parseInt(textNumCustomFeatures.getText()));
        //    configuration.setOscFeatureExtractorSendPort(Integer.parseInt(textExtractorSendPort.getText()));
        //} catch (Exception ex) {
         //   configuration.setNumCustomChuckFeaturesExtracted(0);
         //   textNumCustomFeatures.setText("0");
        //}

        if (radioUseChuckSynth.getModel().isSelected()) {
            configuration.setUseChuckSynthClass(true);
            configuration.setUseOscSynth(false);
        } else {
            configuration.setUseChuckSynthClass(false);
            configuration.setUseOscSynth(true);
            configuration.setOscSynthConfiguration(synthConfiguration);
        }

        configuration.setChuckSynthFilename(labelChuckSynthClass.getText());

        //TODO: Allow user editing of these ports in Osc synth configure panel.
        configuration.setOscSynthReceivePort(12000);
        configuration.setOscSynthSendPort(6448);

        configuration.setIsPlayalongLearningEnabled(checkEnablePlayalong.getModel().isSelected());
        configuration.setPlayalongLearningFile(labelScorePlayer.getText());
    //   }
    }

    private void buttonLoadConfigurationActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonLoadConfigurationActionPerformed
        //Pop up findConfigurationFile dialog box
        //    File file = findConfigurationLoadFile();
        File file = Util.findLoadFile(ChuckConfiguration.getFileExtension(),
                ChuckConfiguration.getFileTypeDescription(),
                ChuckConfiguration.getDefaultLocation(),
                this);
        if (file != null) {
            try {
                //configuration = ChuckConfiguration.loadFromFile(file); //this is where it goes wrong...  TODO
                ChuckConfiguration newC = ChuckConfiguration.readFromFile(file); // This is a problem: New object assigned to reference; main gui maintains old ref value
                configuration.setEqualTo(newC);
                setSynthConfiguration(synthConfiguration);

                updateAllComponents();
            } catch (Exception ex) {
                //TODO: handle:
                System.out.println("Could not load from file");
            }
        }
    }//GEN-LAST:event_buttonLoadConfigurationActionPerformed

    private void setSynthConfiguration(OscSynthConfiguration c) {
        synthConfiguration = configuration.getOscSynthConfiguration();
        if (synthConfiguration != null) {
            synthConfiguration.addChangeListener(synthChangeListener);
        }
    }
    private void buttonSaveConfigurationActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonSaveConfigurationActionPerformed
        setConfigurationFromForm();
        try {
            configuration.validate();
            // File file = findConfigurationSaveFile();
            File file = Util.findSaveFile(ChuckConfiguration.getFileExtension(),
                    ChuckConfiguration.getFileTypeDescription(),
                    ChuckConfiguration.getDefaultLocation(),
                    this);
            if (file != null) {
                try {
                    configuration.writeToFile(file); //TODOTODOTODO: update last path on this.
                    Util.setLastFile(ChuckConfiguration.getFileExtension(), file);
                } catch (Exception ex) {
                    //TODO: handle:
                    System.out.println("Could not save to file");
                }
            }
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(this, ex.getMessage(), "Invalid configuration", JOptionPane.ERROR_MESSAGE);

        }
    }//GEN-LAST:event_buttonSaveConfigurationActionPerformed

    private void checkEnableCustomChuckFeatureActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_checkEnableCustomChuckFeatureActionPerformed
    }//GEN-LAST:event_checkEnableCustomChuckFeatureActionPerformed

    private void buttonOKActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonOKActionPerformed
        setConfigurationFromForm();
        try {
            configuration.validate();
            if (ChuckRunner.getRunnerState() != ChuckRunnerState.NOT_RUNNING) {
                JOptionPane.showMessageDialog(this, "You will have to restart ChucK on the main screen before your changes take effect.", "Changed configuration while chuck running", JOptionPane.INFORMATION_MESSAGE);
            }
            this.dispose();
        //Valid: Give configuration to parent?
        // Save configuration & note location for next time?

        } catch (Exception ex) {
            //Invalid: Pop up a message box, stay open
            //   JOptionPane msgPane = new JOptionPane(ex.getMessage(), JOptionPane.ERROR_MESSAGE);
            //  msgPane.setVisible(true);
            JOptionPane.showMessageDialog(this, ex.getMessage(), "Invalid configuration", JOptionPane.ERROR_MESSAGE);
        }

    }//GEN-LAST:event_buttonOKActionPerformed

    private void buttonCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonCancelActionPerformed
        configuration.setEqualTo(initialConfiguration);
        //Close
        this.dispose();
    }//GEN-LAST:event_buttonCancelActionPerformed

    private void buttonChooseChuckFeatureExtractorActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonChooseChuckFeatureExtractorActionPerformed
        File f = findChuckFeatureFile();
        if (f != null) {
            try {
                labelCustomFeatureExtractor.setText(f.getCanonicalPath());
            } catch (IOException ex) {
                labelCustomFeatureExtractor.setText(f.getAbsolutePath());

            }
        }
    }//GEN-LAST:event_buttonChooseChuckFeatureExtractorActionPerformed

    private void buttonChooseChuckSynthActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonChooseChuckSynthActionPerformed
        File f = findChuckSynthFile();
        if (f != null) {
            try {
                labelChuckSynthClass.setText(f.getCanonicalPath());
            } catch (IOException ex) {
                labelChuckSynthClass.setText(f.getAbsolutePath());

            }
        }
    }//GEN-LAST:event_buttonChooseChuckSynthActionPerformed

    private void buttonChangeChuckExecutableActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonChangeChuckExecutableActionPerformed
        File f = findChuckExecutableFile(); //TODO: have to change this to not be find chuck file, but find executable
        if (f != null) {
            try {
                labelChuckExecutable.setText(f.getCanonicalPath());

            } catch (IOException ex) {
                Logger.getLogger(ChuckConfigurationForm.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
}//GEN-LAST:event_buttonChangeChuckExecutableActionPerformed

    private void buttonChangeWekDirActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonChangeWekDirActionPerformed
        File f = findCoreChuckDirectory(); //TODO: have to change this to not be find chuck file, but find executable
        if (f != null) {
            try {
                labelWekDirCurrent.setText(f.getCanonicalPath());
                // configuration.setChuckDir(f.getCanonicalPath());
                configuration.setWekDir(f.getCanonicalPath());

            } catch (IOException ex) {
                Logger.getLogger(ChuckConfigurationForm.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
}//GEN-LAST:event_buttonChangeWekDirActionPerformed

    private void buttonSaveConfiguration1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonSaveConfiguration1ActionPerformed
        setConfigurationFromForm();
        try {
            configuration.validate();
            File file = findExportChuckFile();
            if (file != null) {
                ChuckRunner.exportConfigurationToChuckFile(configuration, file);
            }
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(this, ex.getMessage(), "Unable to export to file", JOptionPane.ERROR_MESSAGE);
        }
    }//GEN-LAST:event_buttonSaveConfiguration1ActionPerformed

    private void radioUseOSCSynthActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_radioUseOSCSynthActionPerformed
        updateChuckSynthLabelsEnabled();
    }//GEN-LAST:event_radioUseOSCSynthActionPerformed

    private void buttonChoosePlayalongFileActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonChoosePlayalongFileActionPerformed
        File f = findChuckScoreFile();
        if (f != null) {
            try {
                labelScorePlayer.setText(f.getCanonicalPath());
            } catch (IOException ex) {
                labelScorePlayer.setText(f.getAbsolutePath());

            }
        }
}//GEN-LAST:event_buttonChoosePlayalongFileActionPerformed

    private void checkEnablePlayalongActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_checkEnablePlayalongActionPerformed
        // TODO add your handling code here:
    }//GEN-LAST:event_checkEnablePlayalongActionPerformed

    private void buttonEditRealIntegerActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonEditRealIntegerActionPerformed
        OscSynthConfigurationFrame2 f = new OscSynthConfigurationFrame2(synthConfiguration);
        f.setAlwaysOnTop(true);
        f.setVisible(true);
    }//GEN-LAST:event_buttonEditRealIntegerActionPerformed

    private void radioUseChuckSynthActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_radioUseChuckSynthActionPerformed
        updateChuckSynthLabelsEnabled();
    }//GEN-LAST:event_radioUseChuckSynthActionPerformed

    private void updateChuckSynthLabelsEnabled() {
        labelChuckSynthClass.setEnabled(radioUseChuckSynth.isSelected());
        labelChuckSynthLocation.setEnabled(radioUseChuckSynth.isSelected());
        labelOSCSynthProps.setEnabled(!radioUseChuckSynth.isSelected());
    }

    /*    private File findConfigurationLoadFile() {
    JFileChooser fc = new JFileChooser(homePath);
    fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
    boolean success = true;
    File file = null;
    int returnVal = fc.showOpenDialog(this);
    if (returnVal == JFileChooser.APPROVE_OPTION) {
    file = fc.getSelectedFile();
    }

    String lastFile = WekinatorInstance.getWekinatorInstance().getSettings().getLastLocation(ChuckConfiguration.getFileExtension());
    String defaultDir = null;
    if (lastFile == null) {
    defaultDir = ChuckConfiguration.getDefaultLocation();
    }
    FileChooserWithExtension fc = new FileChooserWithExtension(
    ChuckConfiguration.getFileExtension(),
    ChuckConfiguration.getFileTypeDescription(),
    WekinatorInstance.getWekinatorInstance().getSettings().getLastLocation(ChuckConfiguration.getFileExtension()),
    ChuckConfiguration.getDefaultLocation(),
    false);
    File file = null;
    int returnVal = fc.showOpenDialog(this);
    if (returnVal == JFileChooser.APPROVE_OPTION) {
    file = fc.getSelectedFile();
    }
    return file;
    } */

    private File findChuckFeatureFile() {
        //Start looking in chuck dir if possible
        File defaultdir = new File(configuration.getWekDir() + File.separator + "chuck" + File.separator + "feature_extractors");
        String preferredPath = homePath;
        if (defaultdir.exists()) {
            preferredPath = defaultdir.getAbsolutePath();
        }

        JFileChooser fc = new JFileChooser(preferredPath);
        fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
        boolean success = true;
        File file = null;
        int returnVal = fc.showOpenDialog(this);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            file = fc.getSelectedFile();
        }
        return file;
    }

    private File findChuckSynthFile() {
        //Start looking in chuck dir if possible
        File defaultdir = new File(configuration.getWekDir() + File.separator + "chuck" + File.separator + "synths");
        String preferredPath = homePath;
        if (defaultdir.exists()) {
            preferredPath = defaultdir.getAbsolutePath();
        }

        JFileChooser fc = new JFileChooser(preferredPath);
        fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
        boolean success = true;
        File file = null;
        int returnVal = fc.showOpenDialog(this);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            file = fc.getSelectedFile();
        }
        return file;
    }

    private File findChuckScoreFile() {
        //Start looking in chuck dir if possible
        File defaultdir = new File(configuration.getWekDir() + File.separator + "chuck" + File.separator + "score_players");
        String preferredPath = homePath;
        if (defaultdir.exists()) {
            preferredPath = defaultdir.getAbsolutePath();
        }

        JFileChooser fc = new JFileChooser(preferredPath);
        fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
        boolean success = true;
        File file = null;
        int returnVal = fc.showOpenDialog(this);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            file = fc.getSelectedFile();
        }
        return file;
    }

   private File findChuckExecutableFile() {
        //Start looking in chuck dir if possible
        String s = configuration.getWekDir() + File.separator + "chuck" + File.separator + "executable" + File.separator;
        if (File.separator.equals("/")) {
            s += "osx";
        } else {
            s += "win";
        }
        File defaultDir = new File(s);

        String preferredPath = homePath;
        if (defaultDir.exists()) {
            preferredPath = defaultDir.getAbsolutePath();
        }

        JFileChooser fc = new JFileChooser(preferredPath);
        fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
        boolean success = true;
        File file = null;
        int returnVal = fc.showOpenDialog(this);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            file = fc.getSelectedFile();
        }
        return file;

    }

    private File findCoreChuckDirectory() {
        //Start looking in chuck dir if possible
        File wekdir = new File(configuration.getWekDir());
        String preferredPath = homePath;
        if (wekdir.exists()) {
            preferredPath = wekdir.getAbsolutePath();
        } else {
            try {
                File f = new File(Util.getCanonicalPath(new File("")));
                preferredPath = f.getParentFile().getParentFile().getParentFile().getParentFile().getAbsolutePath();
            } catch (Exception ex) {
                preferredPath = Util.getCanonicalPath(new File(""));
            }
        }

        JFileChooser fc = new JFileChooser(preferredPath);
        fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        boolean success = true;
        File file = null;
        int returnVal = fc.showOpenDialog(this);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            file = fc.getSelectedFile();
        }
        return file;
    }

    private File findConfigurationSaveFile() {
        String preferredLoc = configuration.getSaveLocation();
        File tmp = new File(preferredLoc);
        if (!tmp.exists()) {
            preferredLoc = homePath;
        }


        JFileChooser fc = new JFileChooser(preferredLoc);
        fc.setDialogType(JFileChooser.SAVE_DIALOG);
        fc.setFileSelectionMode(JFileChooser.FILES_ONLY);


        int returnVal = fc.showSaveDialog(this);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            return fc.getSelectedFile();
        }
        return null;
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                File f = new File("./");
                ChuckConfiguration c = new ChuckConfiguration();
                new ChuckConfigurationForm(c).setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton buttonCancel;
    private javax.swing.JButton buttonChangeChuckExecutable;
    private javax.swing.JButton buttonChangeWekDir;
    private javax.swing.JButton buttonChooseChuckFeatureExtractor;
    private javax.swing.JButton buttonChooseChuckSynth;
    private javax.swing.JButton buttonChoosePlayalongFile;
    private javax.swing.JButton buttonEditRealInteger;
    private javax.swing.ButtonGroup buttonGroup1;
    private javax.swing.JButton buttonLoadConfiguration;
    private javax.swing.JButton buttonOK;
    private javax.swing.JButton buttonSaveConfiguration;
    private javax.swing.JButton buttonSaveConfiguration1;
    private javax.swing.JCheckBox checkEnableCustomChuckFeature;
    private javax.swing.JCheckBox checkEnablePlayalong;
    private javax.swing.JButton helpCoreChuck;
    private javax.swing.JButton helpFeatures;
    private javax.swing.JButton helpPlayalong;
    private javax.swing.JButton helpSynth;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel15;
    private javax.swing.JLabel jLabel16;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTabbedPane jTabbedPane2;
    private javax.swing.JLabel labelChuckExecutable;
    private javax.swing.JLabel labelChuckSynthClass;
    private javax.swing.JLabel labelChuckSynthLocation;
    private javax.swing.JLabel labelCustomFeatureExtractor;
    private javax.swing.JLabel labelOSCSynthProps;
    private javax.swing.JLabel labelScorePlayer;
    private javax.swing.JLabel labelWekDirCurrent;
    private javax.swing.JLabel labelWekDirHint;
    private javax.swing.JLabel labelWekDirPrompt;
    private javax.swing.JPanel panelFeatures;
    private javax.swing.JPanel panelPlayalong;
    private javax.swing.JPanel panelSetup;
    private javax.swing.JPanel panelSynth;
    private javax.swing.JRadioButton radioUseChuckSynth;
    private javax.swing.JRadioButton radioUseOSCSynth;
    // End of variables declaration//GEN-END:variables

    private void updateAllComponents() {
        labelWekDirCurrent.setText(configuration.getWekDir());
        labelChuckExecutable.setText(configuration.getChuckExecutable());
        checkEnableCustomChuckFeature.getModel().setSelected(configuration.isCustomChuckFeatureExtractorEnabled());
        labelCustomFeatureExtractor.setText(configuration.getCustomChuckFeatureExtractorFilename());
      //  textNumCustomFeatures.setText(Integer.toString(configuration.getNumCustomChuckFeaturesExtracted()));
        //   textExtractorSendPort.setText(Integer.toString(configuration.getOscFeatureExtractorSendPort()));

        //OSC feature: not for plork build
       // checkEnableOSCFeature.getModel().setSelected(configuration.isOscFeatureExtractorEnabled());
       // textNumOscFeatures.setText(Integer.toString(configuration.getNumOSCFeaturesExtracted()));

        if (configuration.isUseChuckSynthClass()) {
            buttonGroup1.setSelected(radioUseChuckSynth.getModel(), true);

        } else {
            buttonGroup1.setSelected(radioUseOSCSynth.getModel(), true);
        }

        labelChuckSynthClass.setText(configuration.getChuckSynthFilename());
        updateChuckSynthLabelsEnabled();


        if (synthConfiguration == null) {
            labelOSCSynthProps.setText("OSC Synth not configured");
        } else {
            updateOscSynthDescription();
        }


        checkEnablePlayalong.getModel().setSelected(configuration.isIsPlayalongLearningEnabled());
        labelScorePlayer.setText(configuration.getPlayalongLearningFile());

        repaint();
    }

    private void updateOscSynthDescription() {
        String s = synthConfiguration.getDescription();
        labelOSCSynthProps.setText(s);
    }
}
